package com.apes.fn.server.vehicleFile.server;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apes.fn.crm.customerExpand.FnCustomerExpand;
import com.apes.fn.scm.retailOrder.model.RetailOrder;
import com.apes.fn.scm.retailOrder.model.RetailOrderItem;
import com.apes.fn.scm.retailOrder.repository.RetailOrderDao;
import com.apes.fn.scm.retailOrder.repository.RetailOrderRepository;
import com.apes.fn.server.servicePlan.model.ServicePlan;
import com.apes.fn.server.vehicleFile.model.*;
import com.apes.fn.server.vehicleFile.repository.VehicleFileAccountRepository;
import com.apes.fn.server.vehicleFile.repository.VehicleFileAreaRepository;
import com.apes.fn.server.vehicleFile.repository.VehicleFileUploadInfoRepository;
import com.apes.fn.server.vehicleFile.server.vehicleFileUploadProcess.CommonUploadProcess;
import com.apes.framework.api.DomainService;
import com.apes.framework.api.SpringManager;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.jpa.spec.model.Filter;
import com.apes.framework.jpa.spec.model.Group;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.plugin.outbox.OutboxEventService;
import com.apes.framework.plugin.outbox.OutboxPayloadWrapper;
import com.apes.framework.plugin.outbox.annotation.OutboxSubscriber;
import com.apes.framework.util.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @program: apes-server
 * @description:
 * @author: czs
 * @create: 2023-11-02 14:14
 **/
@Service("vehicleFileUploadInfoServer")
public class VehicleFileUploadInfoServer extends DomainService {

    @Autowired
    private VehicleFileUploadInfoRepository vehicleFileUploadInfoRepository;
    @Autowired
    private VehicleFileAccountRepository vehicleFileAccountRepository;

    private VehicleFileUploadInfo save(SimpleRequest request){
        VehicleFileUploadInfo vehicleFileUploadInfo = request.getO(VehicleFileUploadInfo.class);
        return vehicleFileUploadInfoRepository.saveAndFlush(vehicleFileUploadInfo);
    }
    private VehicleFileUploadInfo update(SimpleRequest request){
        VehicleFileUploadInfo vehicleFileUploadInfo = request.getO(VehicleFileUploadInfo.class);
        return vehicleFileUploadInfoRepository.saveAndFlush(vehicleFileUploadInfo);
    }

    /**
     * 制单页查询条件过滤
     * @param request
     * @return
     */
    private List findAllList(SimpleRequest request){
        JSONObject jo = request.getJO();
        JSONArray condition = jo.getJSONArray("condition");
        List<Map<String,Object>> newCondition = new ArrayList();
        if (condition != null) {
            for (int i = 0; i < condition.size(); i++) {
                String field = condition.getJSONObject(i).getString("field");
                if ("dept".equals(field)) {
                    Map<String,Object> row = new HashMap();
                    row.put("field", "dept.id");
                    JSONObject value = JSONObject.parseObject(condition.getJSONObject(i).getString("value"));
                    row.put("value", value.getString("id"));
                    row.put("operator", "EQ");
                    newCondition.add(row);
                }else if ("uploaded".equals(field)) {
                    Map<String,Object> row = new HashMap();
                    row.put("field", "uploaded");
                    JSONObject value = JSONObject.parseObject(condition.getJSONObject(i).getString("value"));
                    row.put("value", value.getString("id").equals("1"));
                    row.put("operator", "EQ");
                    newCondition.add(row);
                }else if (LogicalUtil.in(field,"receivableDate","uploadDate")){
                    List op = new ArrayList(Arrays.asList("GTE","LTE"));
                    JSONArray value = condition.getJSONObject(i).getJSONArray("value");
                    for (Object o : value) {
                        Map<String,Object> row = new HashMap();
                        String time = (String) o;
                        Date parse = DateUtil.parse(time, DateUtil.SHOW_DATETIME_FORMAT);
                        row.put("field", field);
                        row.put("value", parse);
                        row.put("operator", op.remove(0));
                        newCondition.add(row);
                    }
                }else if ("carLicense".equals(field)){
                    Map<String,Object> row = new HashMap();
                    row.put("field", "carLicense");
                    JSONObject value = JSONObject.parseObject(condition.getJSONObject(i).getString("value"));
                    row.put("value", value.getString("carLicense"));
                    row.put("operator", "EQ");
                    newCondition.add(row);
                }else {
                    if (field.equals("dept.id")){
                        boolean isDept = true;
                        for (int j = 0; j < condition.size(); j++) {
                            if (condition.getJSONObject(j).getString("field").equals("dept")) {
                                isDept = false;
                            }
                        }
                        if (isDept)newCondition.add(condition.getJSONObject(i));
                    }else {
                        newCondition.add(condition.getJSONObject(i));
                    }

                }

            }
        }
        Group group = new Group();
        group.setFilters(newCondition.stream().map(m1 -> Tools.toBean(Filter.class, m1)).collect(Collectors.toList()));
        return vehicleFileUploadInfoRepository.findAll(JpaDsl.build(group, false),new Sort(Sort.Direction.DESC, "receivableDate"));
    }

    private Map delete(SimpleRequest request){
        VehicleFileUploadInfo vehicleFileUploadInfo = request.getO(VehicleFileUploadInfo.class);
//        VehicleFileUploadInfo.setDeleted(true);
        vehicleFileUploadInfoRepository.delete(vehicleFileUploadInfo);
        return MapUtil.mapper("success",true);
    }

    @OutboxSubscriber(name="生成待上传信息表",condition = "version == 0")
    public void generateVehicleFileUploadInfo(RetailOrder retailOrder){
        //不接收逆向单据
        if ("retailReturn".equals(retailOrder.getOrderType()))return;
        VehicleFileAccount vehicleFileAccount = vehicleFileAccountRepository.findOne(JpaDsl.toCriteria("belongDept", "EQ", retailOrder.getDept())).orElse(null);
        if (vehicleFileAccount==null)return;
        FnCustomerExpand customerExpand = retailOrder.getCustomerExpand();
        List<RetailOrderItem> orderItems = retailOrder.getSaleItems().stream().filter(retailOrderItem -> retailOrderItem.getProduct().getServeType() != null && retailOrderItem.getProduct().getServeType().isVehicleFileUpload()).collect(Collectors.toList());
        if (orderItems.isEmpty())return;
        if (customerExpand==null)return;
        if (customerExpand.getCarLicense()==null)return;
        VehicleFileUploadInfo vehicleFileUploadInfo = new VehicleFileUploadInfo();
        vehicleFileUploadInfo.setCreator(retailOrder.getClerk().getId());
        vehicleFileUploadInfo.setOrderId(retailOrder.getId());
        vehicleFileUploadInfo.setOrderType(RetailOrder.class.getSimpleName());
        vehicleFileUploadInfo.setDept(retailOrder.getDept());

        vehicleFileUploadInfo.setFnCustomerExpand(customerExpand);
        vehicleFileUploadInfo.setRealName(customerExpand.getRealname());
        vehicleFileUploadInfo.setCarLicense(customerExpand.getCarLicense());
        vehicleFileUploadInfo.setReceivableDate(retailOrder.getCreateDate()==null?new Date():retailOrder.getCreateDate());
        double actualAmount = orderItems.stream().mapToDouble(item -> Arith.sub(item.getPriceSubtotal() + item.getPriceTax(), item.getDiscountAmount())).sum();
        vehicleFileUploadInfo.setActualAmount(actualAmount);
        //获取末级分类 乘数量
        List<String> collect = orderItems.stream().map(retailOrderItem -> retailOrderItem.getProduct().getClassify().getName()).collect(Collectors.toList());
        StringBuffer sf = new StringBuffer();
        Map<String,Integer> map = new HashMap();
        collect.forEach(s -> map.merge(s, 1, Integer::sum));

        Iterator<String> iterator = map.keySet().iterator();
        while (iterator.hasNext()){
            String next = iterator.next();
            Integer integer = map.get(next);
            sf.append(next+"X"+integer+";");
        }
        vehicleFileUploadInfo.setServeTypes(sf.toString());
        vehicleFileUploadInfo = vehicleFileUploadInfoRepository.saveAndFlush(vehicleFileUploadInfo);
        pushOutboxUploadInfo(vehicleFileUploadInfo);
        vehicleFileUploadInfoRepository.saveAndFlush(vehicleFileUploadInfo);
    }

    /**
     *
     * @param vehicleFileUploadInfo
     */
    private void pushOutboxUploadInfo(VehicleFileUploadInfo vehicleFileUploadInfo) {
        JSONObject json = new JSONObject();
        json.put("id", vehicleFileUploadInfo.getId());
        // 推送消息
        OutboxPayloadWrapper wrapper = new OutboxPayloadWrapper();
        wrapper.setSubscriber("fn.vehicleFile.uploadVehicleFileUploadInfo");
        wrapper.setAggregateId("VF:"+vehicleFileUploadInfo.getId());
        wrapper.setPayload(json.toJSONString());
        SpringManager.getBean(OutboxEventService.class).sendSaveEvent(wrapper);
        vehicleFileUploadInfo.setUploadMsg("正在上传中!");
    }

    @OutboxSubscriber(id="fn.vehicleFile.uploadVehicleFileUploadInfo",name="上传车辆健康档案")
    public void uploadVehicleFileUploadInfo(OutboxPayloadWrapper wrapper){
        String payload = wrapper.getPayload();
        JSONObject jsonObject = JSONObject.parseObject(payload);
        VehicleFileUploadInfo vehicleFileUploadInfo = vehicleFileUploadInfoRepository.findOne(jsonObject.getString("id"));
        VehicleFileAccount vehicleFileAccount = vehicleFileAccountRepository.findOne(JpaDsl.toCriteria("belongDept", "EQ", vehicleFileUploadInfo.getDept())).orElse(null);
        if (vehicleFileAccount==null)return;
        upload(vehicleFileUploadInfo, vehicleFileAccount);
    }

    private void upload(VehicleFileUploadInfo vehicleFileUploadInfo, VehicleFileAccount vehicleFileAccount) {
        String msg = "";
        boolean isUpload = true;
        VehicleFileArea vehicleFileArea = vehicleFileAccount.getVehicleFileArea();
        List<VehicleFileAreaEnum> vehicleFileAreaEnums = Arrays.stream(VehicleFileAreaEnum.values())
                .filter(vehicleFileAreaEnum -> vehicleFileAreaEnum.getName().equals(vehicleFileArea.getApiType()))
                .collect(Collectors.toList());
        if (vehicleFileAreaEnums.isEmpty()) throw new RuntimeException("没有合适的处理器");
        CommonUploadProcess commonUploadProcess = VehicleFileAreaEnum.nameFind(vehicleFileArea.getApiType());
        try {
            commonUploadProcess.upload(vehicleFileAccount, vehicleFileUploadInfo);
        } catch (Exception e) {
            e.printStackTrace();
            msg = e.getMessage();
            isUpload = false;
        }
        if ("token不存在或已失效".equals(msg)){
            vehicleFileAccount.setTokenEndDate(null);
            vehicleFileAccount.setTokenStartDate(null);
            vehicleFileAccount.setToken(null);
            vehicleFileAccountRepository.saveAndFlush(vehicleFileAccount);
        }
        vehicleFileUploadInfo.setUploadMsg(msg);
        vehicleFileUploadInfo.setUploadDate(new Date());
        vehicleFileUploadInfo.setUploaded(isUpload);
        vehicleFileUploadInfo.setUploadPlatform(vehicleFileArea.getName());
        vehicleFileUploadInfoRepository.saveAndFlush(vehicleFileUploadInfo);
    }

    private boolean reUpload(SimpleRequest request){
        VehicleFileUploadVo vehicleFileUploadVo = request.getO(VehicleFileUploadVo.class);
        if (vehicleFileUploadVo.getDeptId() ==null)throw new RuntimeException("请用使用门店账号");
        if (vehicleFileUploadVo.getOperator() ==null)throw new RuntimeException("上传人不能为空");
        List<VehicleFileAccount> accountList = vehicleFileAccountRepository.findAll(JpaDsl.toCriteria("belongDept.id", "EQ", vehicleFileUploadVo.getDeptId()));
        if (accountList.isEmpty())throw new RuntimeException("请配置有效账号");
        List<VehicleFileUploadInfo> vehicleFileUploadInfos = vehicleFileUploadVo.getVehicleFileUploadInfos();
        vehicleFileUploadInfos.stream()
                .filter(vehicleFileUploadInfo -> !vehicleFileUploadInfo.isUploaded())
                .forEach(this::pushOutboxUploadInfo);
        //如果改为同步配置会报乐观锁
        vehicleFileUploadInfoRepository.saveAll(vehicleFileUploadInfos);
        return true;
    }

    private JSONArray runWaitUploadData(SimpleRequest request){
        JSONObject jo = request.getJO();
        JSONArray allNotUploadData = SpringManager.getBean(RetailOrderDao.class).findAllNotUploadData(new JSONObject(
                MapUtil.mapper(
                        "DEPT_ID", jo.getString("DEPT_ID"),
                        "startDate",jo.getDate("startDate"),
                        "endDate",jo.getDate("endDate")
                )
        ));
        return allNotUploadData;
    }
    private JSONArray runWaitUploadDataForNow(SimpleRequest request){
        JSONObject jo = request.getJO();
        JSONArray allNotUploadData = SpringManager.getBean(RetailOrderDao.class).findAllNotUploadData(new JSONObject(
                MapUtil.mapper(
                        "DEPT_ID", jo.getString("DEPT_ID"),
                        "startDate",jo.getDate("startDate"),
                        "endDate",jo.getDate("endDate")
                )
        ));
        for (Object allNotUploadDatum : allNotUploadData) {
            JSONObject jsonObject = (JSONObject) allNotUploadDatum;
            String id = jsonObject.getString("ID");
            RetailOrder retailOrder = SpringManager.getBean(RetailOrderRepository.class).findOne(id);
            generateVehicleFileUploadInfo(retailOrder);
        }
//        String id = jo.getString("id");
//        generateVehicleFileUploadInfo(SpringManager.getBean(RetailOrderRepository.class).findOne(id));
//        return null;
        return allNotUploadData;
    }

    private void saveWaitUploadData(SimpleRequest request){
        JSONObject jo = request.getJO();
        String id = jo.getString("ID");
        RetailOrder retailOrder = SpringManager.getBean(RetailOrderRepository.class).findOne(id);
        generateVehicleFileUploadInfo(retailOrder);
    }
    private void register(SimpleRequest request){
        JSONObject jo = request.getJO();
        String id = jo.getString("ID");
        RetailOrder retailOrder = SpringManager.getBean(RetailOrderRepository.class).findOne(id);
        generateVehicleFileUploadInfo(retailOrder);
    }

}
